'use strict';

const Controller = require('egg').Controller;

/**
 * 审批流控制器
 * 处理审批的发起、处理、查询等功能
 */
class ApprovalController extends Controller {
  /**
   * 获取审批统计信息
   * @returns {Promise<void>}
   */
  async getStatistics() {
    const {
      ctx
    } = this;

    try {

      // 调用service层方法获取统计数据
      const statistics = await ctx.service.approval.getApprovalStatistics({
        person_id: ctx.state.user.person_id
      });

      ctx.body = statistics
    } catch (error) {
      ctx.throw(400, error)
    }
  }

  /**
   * 发起审批
   * @param {Object} ctx.request.body
   * @param {string} ctx.request.body.title - 审批标题
   * @param {string} ctx.request.body.content - 审批内容
   * @param {number} ctx.request.body.applicant_id - 申请人ID
   * @param {string} [ctx.request.body.work_members] - 工作成员，多个人员ID用逗号分隔
   * @param {string} ctx.request.body.estimated_start_date - 预计开始时间，格式：YYYY-MM-DD
   * @param {string} ctx.request.body.estimated_end_date - 预计结束时间，格式：YYYY-MM-DD
   * @param {Array} ctx.request.body.approvers - 审批人列表，包含level和approver_id
   * @param {Array} ctx.request.body.output_types - 产出类型列表，可选值：新媒体图文、新媒体视频、广播电视类
   * @throws {422} 参数验证失败时抛出异常
   */
  async create() {
    const {
      ctx
    } = this;

    console.log(ctx.request.body)

    // 验证参数
    ctx.validate({
      title: {
        type: 'string',
        required: true
      },
      content: {
        type: 'string',
        required: true
      },
      applicant_id: {
        type: 'number',
        required: true
      },
      work_members: {
        type: 'string',
        required: false
      },
      estimated_start_date: {
        type: 'string',
        required: true,
        format: /^\d{4}-\d{2}-\d{2}$/
      },
      estimated_end_date: {
        type: 'string',
        required: true,
        format: /^\d{4}-\d{2}-\d{2}$/
      },
      approvers: {
        type: 'array',
        required: true,
        itemType: 'object',
        rule: {
          level: {
            type: 'number',
            required: true,
            min: 1,
            max: 3
          },
          approver_id: {
            type: 'number',
            required: true
          }
        }
      },
      output_types: {
        type: 'array',
        required: true,
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.create(ctx.request.body);
    ctx.body = result;
  }

  /**
   * 获取审批列表
   * 支持按状态、申请人、审批人等多维度筛选
   * @param {Object} ctx.request.body
   * @param {string} [ctx.request.body.status] - 审批状态
   * @param {number} [ctx.request.body.applicant_id] - 申请人ID
   * @param {number} [ctx.request.body.approver_id] - 审批人ID
   * @param {string} [ctx.request.body.start_date] - 开始日期
   * @param {string} [ctx.request.body.end_date] - 结束日期
   * @param {number} [ctx.request.body.page=1] - 页码
   * @param {number} [ctx.request.body.page_size=10] - 每页条数
   */
  async list() {
    const {
      ctx
    } = this;

    // 验证参数
    ctx.validate({
      status: {
        type: 'enum',
        values: ['pending', 'processing', 'approved', 'rejected', 'withdrawn'],
        required: false
      },
      applicant_id: {
        type: 'number',
        required: false
      },
      approver_id: {
        type: 'number',
        required: false
      },
      start_date: {
        type: 'string',
        required: false,
        format: /^\d{4}-\d{2}-\d{2}$/
      },
      end_date: {
        type: 'string',
        required: false,
        format: /^\d{4}-\d{2}-\d{2}$/
      },
      page: {
        type: 'number',
        required: false,
        min: 1
      },
      page_size: {
        type: 'number',
        required: false,
        min: 1,
        max: 100
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.findAll(ctx.request.body);
    ctx.body = result;
  }

  /**
   * 获取单个审批详情
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.application_id - 审批申请ID
   * @throws {404} 未找到该审批时抛出异常
   */
  async getById() {
    const {
      ctx
    } = this;
    const {
      application_id
    } = ctx.request.body;

    // 验证参数
    ctx.validate({
      application_id: {
        type: 'number',
        required: true
      }
    });

    const approval = await ctx.service.approval.findById(application_id);
    if (!approval) {
      ctx.throw(404, '未找到该审批');
    }
    ctx.body = approval;
  }

  /**
   * 处理审批
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.application_id - 审批申请ID
   * @param {number} ctx.request.body.flow_id - 审批流程ID
   * @param {number} ctx.request.body.approver_id - 审批人ID
   * @param {string} ctx.request.body.result - 审批结果：approved-同意 rejected-拒绝
   * @param {string} [ctx.request.body.comment] - 审批意见
   * @throws {422} 参数验证失败时抛出异常
   * @throws {403} 无权限处理该审批时抛出异常
   */
  async handle() {
    const {
      ctx
    } = this;

    // 验证参数
    ctx.validate({
      application_id: {
        type: 'number',
        required: true
      },
      flow_id: {
        type: 'number',
        required: true
      },
      approver_id: {
        type: 'number',
        required: true
      },
      result: {
        type: 'enum',
        values: ['approved', 'rejected'],
        required: true
      },
      comment: {
        type: 'string',
        required: false
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.handleApproval(ctx.request.body);
    if (result.error === 'flow_not_found') {
      ctx.throw(404, '审批流程不存在');
    }
    if (result.error === 'no_permission') {
      ctx.throw(403, '您无权处理该审批');
    }
    if (result.error === 'already_processed') {
      ctx.throw(422, '该审批已处理');
    }
    if (result.error === 'application_not_found') {
      ctx.throw(404, '审批申请不存在');
    }
    if (result.error === 'not_current_level') {
      ctx.throw(422, '当前审批尚未流转到该级别');
    }

    ctx.body = result;
  }

  /**
   * 撤回审批
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.application_id - 审批申请ID
   * @param {number} ctx.request.body.applicant_id - 申请人ID
   * @throws {422} 参数验证失败时抛出异常
   * @throws {403} 无权限撤回该审批时抛出异常
   */
  async withdraw() {
    const {
      ctx
    } = this;

    // 验证参数
    ctx.validate({
      application_id: {
        type: 'number',
        required: true
      },
      applicant_id: {
        type: 'number',
        required: true
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.withdrawApproval(
      ctx.request.body.application_id,
      ctx.request.body.applicant_id
    );

    if (result.error === 'no_permission') {
      ctx.throw(403, '您无权撤回该审批');
    }

    if (result.error === 'cannot_withdraw') {
      ctx.throw(422, '该审批已处理，无法撤回');
    }

    ctx.body = result;
  }

  /**
   * 获取用户待审批列表
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.approver_id - 审批人ID
   * @param {number} [ctx.request.body.page=1] - 页码
   * @param {number} [ctx.request.body.page_size=10] - 每页条数
   */
  async getPendingList() {
    const {
      ctx
    } = this;

    // 验证参数
    ctx.validate({
      approver_id: {
        type: 'number',
        required: true
      },
      page: {
        type: 'number',
        required: false,
        min: 1
      },
      page_size: {
        type: 'number',
        required: false,
        min: 1,
        max: 100
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.findPendingByApprover(ctx.request.body);
    ctx.body = result;
  }

  /**
   * 获取用户已审批列表
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.approver_id - 审批人ID
   * @param {number} [ctx.request.body.page=1] - 页码
   * @param {number} [ctx.request.body.page_size=10] - 每页条数
   */
  async getApprovedList() {
    const {
      ctx
    } = this;

    // 验证参数
    ctx.validate({
      approver_id: {
        type: 'number',
        required: true
      },
      page: {
        type: 'number',
        required: false,
        min: 1
      },
      page_size: {
        type: 'number',
        required: false,
        min: 1,
        max: 100
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.findApprovedByApprover(ctx.request.body);
    ctx.body = result;
  }

  /**
   * 获取用户发起的审批列表
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.applicant_id - 申请人ID
   * @param {string} [ctx.request.body.status] - 审批状态
   * @param {number} [ctx.request.body.page=1] - 页码
   * @param {number} [ctx.request.body.page_size=10] - 每页条数
   */
  async getMyApplications() {
    const {
      ctx
    } = this;

    // 验证参数
    ctx.validate({
      applicant_id: {
        type: 'number',
        required: true
      },
      status: {
        type: 'enum',
        values: ['pending', 'processing', 'approved', 'rejected', 'withdrawn'],
        required: false
      },
      page: {
        type: 'number',
        required: false,
        min: 1
      },
      page_size: {
        type: 'number',
        required: false,
        min: 1,
        max: 100
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.findMyApplications(ctx.request.body);
    ctx.body = result;
  }

  /**
   * 更新产出记录
   * 用于对象存储上传附件后，将相关信息写入记录中
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.attachment_id - 产出记录ID
   * @param {number} ctx.request.body.application_id - 审批申请ID
   * @param {number} ctx.request.body.uploaded_by - 上传人ID
   * @param {string} [ctx.request.body.file_url] - 附件URL
   * @param {string} [ctx.request.body.file_name] - 文件名
   * @param {number} [ctx.request.body.file_size] - 文件大小(字节)
   * @param {string} [ctx.request.body.description] - 产出说明
   * @param {string} [ctx.request.body.status] - 状态：pending-待上传 completed-已完成
   * @throws {422} 参数验证失败时抛出异常
   * @throws {403} 无权限更新该产出记录时抛出异常
   */
  async updateOutput() {
    const {
      ctx
    } = this;

    // 验证参数
    ctx.validate({
      attachment_id: {
        type: 'number',
        required: true
      },
      application_id: {
        type: 'number',
        required: true
      },
      uploaded_by: {
        type: 'number',
        required: true
      },
      file_url: {
        type: 'string',
        required: false
      },
      file_name: {
        type: 'string',
        required: false
      },
      file_size: {
        type: 'number',
        required: false,
        min: 0
      },
      description: {
        type: 'string',
        required: false
      },
      status: {
        type: 'enum',
        values: ['pending', 'completed'],
        required: false
      }
    }, ctx.request.body);

    const result = await ctx.service.approval.updateOutput(ctx.request.body);

    if (result.error === 'not_found') {
      ctx.throw(404, '未找到该产出记录');
    }

    ctx.body = result;
  }

  /**
   * 获取审批的产出记录列表
   * @param {Object} ctx.request.body
   * @param {number} ctx.request.body.application_id - 审批申请ID
   * @throws {404} 未找到该审批时抛出异常
   */
  async getOutputs() {
    const {
      ctx
    } = this;
    const {
      application_id
    } = ctx.request.body;

    // 验证参数
    ctx.validate({
      application_id: {
        type: 'number',
        required: true
      }
    });

    const outputs = await ctx.service.approval.findOutputsByApplicationId(application_id);
    ctx.body = outputs;
  }

  /**
   * 获取与指定人员相关的审批申请（作为申请人或工作成员）
   * @returns {Promise<void>}
   */
  async getApplicationsByPerson() {
    const {
      ctx
    } = this;

    try {
      // 获取请求参数
      const {
        person_id,
        page = 1,
        page_size = 10
      } = ctx.request.body;

      // 验证必填参数
      if (!person_id) {
        ctx.throw(400, '人员ID不能为空')
      }

      // 调用service层方法
      const result = await ctx.service.approval.getApplicationsByPerson({
        person_id,
        page,
        page_size
      });
      ctx.body = result;
    } catch (error) {
      ctx.throw(500, error)
    }
  }
}

module.exports = ApprovalController;